1 : <?php
2 : /*--------------------------------------------------------------------------+
3 : This file is part of eStudy.
4 : common/classes/class.utilities.inc.php
5 : - Modulgruppe: Framework
6 : - Beschreibung: Verschiedene hilfreiche Funktionen.
7 : - Version: 0.3, 29/02/04
8 : - Autor(en): Jens Brueck <jb@bk-tech.net>
9 : +---------------------------------------------------------------------------+
10 : This program is free software; you can redistribute it and/or
11 : modify it under the terms of the GNU General Public License
12 : as published by the Free Software Foundation; either version 2
13 : of the License, or any later version.
14 : +---------------------------------------------------------------------------+
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 : You should have received a copy of the GNU General Public License
20 : along with this program; if not, write to the Free Software
21 : Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 : +--------------------------------------------------------------------------*/
23 : /**
24 : * In dieser Datei befindet sich die Implementierung der Klasse Utilities.
25 : *
26 : * @package eStudy.Framework
27 : * @version 0.3, 29/02/04
28 : * @author Jens Brueck <jb@bk-tech.net>
29 : */
30 : require_once (PATH_TO_ROOT."common/classes/class.bbcode.inc.php");
31 : /**
32 : * verschiedene hilfreiche Funktionen.
33 : *
34 : * @author Jens Brueck (jb@bk-tech.net)
35 : * @version 0.3, 29/02/04
36 : * @package eStudy.Framework
37 : */
38 : class Utilities {
39 : /**
40 : * Fuegt alle GET-Variablen zu einem String zusammen.
41 : * Der String kann in URLs weiterverwendet werden.
42 : *
43 : * @static
44 : * @author Jens Brueck (jb@bk-tech.net)
45 : * @version 0.1, 06/05/03
46 : * @access public
47 : * @return string Form: ?Varname1=Varvalue1&Varname2=Varvalue2&...
48 : */
49 : function concatGetVars() {
50 0 : if (isset($_GET) && count($_GET) > 0) {
51 0 : foreach($_GET as $getVarName => $getVarValue) {
52 0 : $getVars[] = urlencode($getVarName) ."=".urlencode($getVarValue);
53 0 : }
54 0 : return "?".implode($getVars, "&");
55 0 : } else return "";
56 : }
57 : /**
58 : * Holt die naechste freie ID aus einer DB- Tabellen-Spalte.
59 : * Ersatz fuer die auto_increment-Funktion der DB, die immer
60 : * die naechste ID nach der zuletzt vergebenen liefert.
61 : * Diese Funktion dient also dazu, Luecken in einer Spalte
62 : * zu vermeiden.
63 : * Vor der Ausfuehrung der Funktion sollte die betreffende Tabelle
64 : * UNBEDINGT mit 'LOCK TABLES tabelle WRITE' gelocked werden! Statt
65 : * WRITE kann je nach Einsatzzweck auch READ verwendet werden.
66 : *
67 : * @access public
68 : * @author Jens Brueck (jb@bk-tech.net)
69 : * @version 0.1, 06/05/03
70 : * @param string $table Betreffende Tabelle.
71 : * @param string $col Betreffende Spalte.
72 : * @return integer naechste freie ID.
73 : */
74 : function nextFreeID($table, $col) {
75 0 : global $db;
76 0 : $nextFreeID = 0;
77 0 : $ids = $db->get_col("SELECT $col FROM $table ORDER BY ID");
78 0 : if ($ids) {
79 0 : foreach($ids as $id) if ($id != ++$nextFreeID) break;
80 0 : } else {
81 0 : $nextFreeID = 1;
82 : }
83 0 : if ($nextFreeID == $ids[count($ids) -1]) $nextFreeID++;
84 0 : return $nextFreeID;
85 : }
86 : /**
87 : * Gibt einen Link zu einem Hilfetext aus.
88 : * An der Stelle des Funktionsaufrufs wird ein Fragezeichen ausgegeben.
89 : * Bei Klick auf das Fragezeichen oeffnet sich ein Fenster mit einem
90 : * Hilfetext.
91 : *
92 : * @access public
93 : * @author Jens Brueck (jb@bk-tech.net)
94 : * @version 0.1, 06/05/03
95 : * @param integer $helpID - ID des Hilfetextes, der im Fenster angezeigt werden soll,
96 : * aus der Tabelle helptexts.
97 : * @return void
98 : */
99 : function help($helpID = false) {
100 0 : echo Utilities::helpCode($helpID);
101 0 : }
102 : /**
103 : * Gibt einen Link zu einem Hilfetext zurück.
104 : * An der Stelle des Funktionsaufrufs wird ein Fragezeichen ausgegeben.
105 : * Bei Klick auf das Fragezeichen oeffnet sich ein Fenster mit einem
106 : * Hilfetext.
107 : *
108 : * @access public
109 : * @version 0.1, 11/27/06
110 : * @param integer $helpID - ID des Hilfetextes, der im Fenster angezeigt werden soll,
111 : * aus der Tabelle helptexts.
112 : * @return void
113 : */
114 : function getHelp($helpID = false) {
115 0 : return Utilities::helpCode($helpID);
116 : }
117 : /**
118 : * Gibt einen Link zu einem Hilfetext zurück !!
119 : * An der Stelle des Funktionsaufrufs wird ein Fragezeichen ausgegeben.
120 : * Bei Klick auf das Fragezeichen oeffnet sich ein Fenster mit einem
121 : * Hilfetext.
122 : *
123 : * @access public
124 : * @author Mirko Pitz
125 : * @version 0.1, 20/06/04
126 : * @param integer $helpID - ID des Hilfetextes, der im Fenster angezeigt werden soll,
127 : * aus der Tabelle helptexts.
128 : * @return void
129 : */
130 : function helpCode($helpID = false) {
131 2 : if (is_numeric($helpID)) {
132 2 : global $db;
133 2 : $caption = $db->get_var(sprintf("SELECT Caption FROM helptexts WHERE ID='%s'", $helpID));
134 2 : $code = "";
135 2 : if (!empty($caption)) {
136 2 : $code = "<a href='".PATH_TO_ROOT."help.php?id=$helpID' ";
137 2 : $code.= "onclick='window.open(\"".PATH_TO_ROOT."help.php?id=$helpID\",\"HelpWindow\",\"location=no,resizable=yes,width=400,height=500,left=40,top=40,dependent=yes\");return false;' ";
138 2 : $code.= "title='Hilfe zu \"$caption\" (öffnet in neuem Fenster)' ";
139 2 : $code.= "class='quick_help'>?</a>";
140 2 : }
141 2 : return $code;
142 : }
143 0 : return "";
144 : }
145 : /**
146 : * Prüft, ob ein String nur Zeichen enthält, die für einen Login-Namen
147 : * zulässig sind.
148 : *
149 : * @static
150 : * @access public
151 : * @param string $login - der Loginname der überprüft werden soll
152 : * @return bool
153 : */
154 : function validateLoginName($login) {
155 0 : return ereg("^[a-zA-Z_0-9-]*$", trim($login));
156 : }
157 : /**
158 : * Rekursive Version von mkdir() zum Erstellen von mehreren
159 : * Verzeichnisebenen
160 : *
161 : * @access public
162 : * @param string $path - vollständiger zu erstellender Pfad
163 : * @param integer $rights - Zugriffsrechte, mit denen die Verzeichnisse
164 : * erstellt werden sollen
165 : * @return bool - Erfolgswert
166 : */
167 : function mkdir_r($path, $rights = 0777) {
168 0 : if (!file_exists($path)) {
169 0 : if (Utilities::mkdir_r(dirname($path), $rights)) return mkdir($path, $rights);
170 0 : }
171 0 : return true;
172 : }
173 : /**
174 : * Funktion zum Sortieren eines mehrdimensionalen Arrays
175 : *
176 : * @access public
177 : * @param array $array - Zu sortierendes Array
178 : * @param mixed $key - Index (String oder Integer), nach dem sortiert werden soll
179 : * @param string $order - Aufsteigend ("ASC") oder absteigend ("DESC")
180 : * @return array - Sortiertes Array
181 : */
182 : function sortMultiArray($array, $key, $order = "ASC") {
183 0 : foreach($array as $i => $k) {
184 0 : $sort_values[$i] = $array[$i][$key];
185 0 : }
186 0 : asort($sort_values);
187 0 : if ($order == "DESC") $sort_values = array_reverse($sort_values, true);
188 0 : reset($sort_values);
189 0 : while (list($arr_key, $arr_val) = each($sort_values)) {
190 0 : $sorted_arr[$arr_key] = $array[$arr_key];
191 0 : }
192 0 : return $sorted_arr;
193 : }
194 : // B.S.
195 : /**
196 : * Generiert ein Cache Objekt für user sessions zur Verminderung von DB Abfragen
197 : *
198 : * @access public
199 : * @return array - Cache Objekt
200 : */
201 : function getUnserializeSessionCacheObject($sessions) {
202 0 : global $db;
203 : // Array{user.ID,session.variable)
204 0 : $sessionIDCache = array();
205 0 : $userIDCache = array();
206 0 : if (sizeof($sessions) > 0) {
207 0 : foreach($sessions as $session) {
208 0 : $sID = $session->sessionID;
209 0 : $sessionIDCache["$sID"] = $session->variable;
210 0 : $uID = $session->userID;
211 0 : $userIDCache["$uID"] = $session->variable;
212 0 : }
213 0 : }
214 : $cacheObject = array(
215 0 : 'users' => $userIDCache,
216 : 'sessions' => $sessionIDCache
217 0 : );
218 0 : return $cacheObject;
219 : }
220 : /**
221 : * Funktion zum Zurückgeben der Daten einer Session in einem identisch
222 : * aufgebauten Array.
223 : * Siehe http://www.php.net/manual/en/function.session-decode.php.
224 : *
225 : * @access public
226 : * @author Clemens Weiß <clemens.weiss@mni.fh-giessen.de>
227 : * @param mixed $ID string - ID der auszulesenden Session
228 : * integer - ID des Benutzers, um dessen Session es geht
229 : * @return array - Session-Daten in einem Array, oder null falls Session nicht gültig
230 : */
231 : function unserializeSession($ID, $cacheObject = null) {
232 0 : global $db, $settings;
233 0 : if ($cacheObject != null) {
234 0 : if (is_int($ID)) {
235 0 : $users = $cacheObject["users"];
236 0 : $str = $users["$ID"];
237 0 : }
238 : else {
239 0 : $sessions = $cacheObject["sessions"];
240 0 : $str = $sessions["$ID"];
241 : }
242 0 : if ($str == null)
243 0 : return null;
244 0 : }
245 : else {
246 0 : if (is_int($ID)) {
247 0 : $ID = $db->get_var("SELECT sessionID FROM user WHERE ID='$ID'");
248 0 : }
249 0 : $str = $db->get_var("SELECT variable FROM session WHERE id='$ID'");
250 0 : if ($str == null)
251 0 : return null;
252 : }
253 0 : mb_internal_encoding("ISO-8859-1");
254 0 : $endptr = strlen($str);
255 0 : $p = 0;
256 0 : $serialized = '';
257 0 : $items = 0;
258 0 : $level = 0;
259 0 : while ($p < $endptr) {
260 0 : $q = $p;
261 0 : while ($str[$q] != "|") if (++$q >= $endptr) break 2;
262 0 : if ($str[$p] == "!") {
263 0 : $p++;
264 0 : $has_value = false;
265 0 : } else {
266 0 : $has_value = true;
267 : }
268 0 : $name = substr($str, $p, $q-$p);
269 0 : $q++;
270 0 : $serialized.= 's:'.strlen($name) .':"'.$name.'";';
271 0 : if ($has_value) {
272 0 : for ( ; ;) {
273 0 : $p = $q;
274 0 : switch ($str[$q]) {
275 0 : case 'N': /* null */
276 0 : case 'b': /* boolean */
277 0 : case 'i': /* integer */
278 0 : case 'd': /* decimal */
279 0 : do $q++;
280 0 : while (($q < $endptr) && ($str[$q] != ';'));
281 0 : $q++;
282 0 : $serialized.= substr($str, $p, $q-$p);
283 0 : if ($level == 0) break 2;
284 0 : break;
285 :
286 0 : case 'R': /* reference */
287 0 : $q+= 2;
288 0 : for ($id = '' ; ($q < $endptr) && ($str[$q] != ';') ; $q++) $id.= $str[$q];
289 0 : $q++;
290 0 : $serialized.= 'R:'.($id+1) .';'; /* increment pointer because of outer array */
291 0 : if ($level == 0) break 2;
292 0 : break;
293 :
294 0 : case 's': /* string */
295 0 : $q+= 2;
296 0 : for ($length = '' ; ($q < $endptr) && ($str[$q] != ':') ; $q++) $length.= $str[$q];
297 0 : $q+= 2;
298 0 : $q+= (int)$length+2;
299 0 : $serialized.= substr($str, $p, $q-$p);
300 0 : if ($level == 0) break 2;
301 0 : break;
302 :
303 0 : case 'a': /* array */
304 0 : case 'O': /* object */
305 0 : do $q++;
306 0 : while (($q < $endptr) && ($str[$q] != '{'));
307 0 : $q++;
308 0 : $level++;
309 0 : $serialized.= substr($str, $p, $q-$p);
310 0 : break;
311 :
312 0 : case '}': /* end of array|object */
313 0 : $q++;
314 0 : $serialized.= substr($str, $p, $q-$p);
315 0 : if (--$level == 0) break 2;
316 0 : break;
317 :
318 0 : default:
319 0 : return false;
320 0 : }
321 0 : }
322 0 : } else {
323 0 : $serialized.= 'N;';
324 0 : $q+= 2;
325 : }
326 0 : $items++;
327 0 : $p = $q;
328 0 : }
329 0 : mb_internal_encoding("UTF-8");
330 0 : return @unserialize('a:'.$items.':{'.$serialized.'}');
331 : }
332 : /**
333 : * Gibt zurück, ob ein Benutzer (bestimmt durch Benutzer-ID oder Session-
334 : * ID) online oder offline ist.
335 : *
336 : * @access public
337 : * @author Clemens Weiß <clemens.weiss@mni.fh-giessen.de>
338 : * @param mixed $ID - Session-ID oder Benutzer-ID
339 : * @return bool false: offline, true: online.
340 : */
341 : function userOnline($ID, $cacheObject = null) {
342 0 : global $settings;
343 0 : $userSession = Utilities::unserializeSession($ID, $cacheObject);
344 0 : if (is_array($userSession) && isset($userSession["lastaccess"]) && $userSession["lastaccess"]+($settings["online_timeout"]*60) > time() && isset($userSession["userid"])) return true;
345 0 : return false;
346 : }
347 : /**
348 : * Gibt zurück, ob eine URL syntaktisch korrekt ist
349 : *
350 : * @static
351 : * @access public
352 : * @author Clemens Weiß <clemens.weiss@mni.fh-giessen.de>
353 : * @param string $url - zu überprüfende URL
354 : * @return bool true: URL korrekt, false: URL nicht korrekt
355 : */
356 : function validateURL($url) {
357 0 : return preg_match("/^(http|https|ftp):\/\/([a-z0-9\.\-@:]+)[a-z0-9;\/\?:@=&\$\-_\.\+!\*'\(\),#%~ ]*?$/i", $url);
358 : }
359 : /**
360 : * Erstellt aus einem zweidimensionalen Array ein neues Array, in dem die Werte des angegebenen
361 : * Indexes der assoziativen zweiten Dimension des alten Arrays die Indexe der ersten Dimension
362 : * des neuen Arrays sind.
363 : * Bsp.:
364 : * <pre>$array_a:
365 : * Array
366 : * (
367 : * [0] => Array
368 : * (
369 : * [ID] => 8
370 : * [Name] => Max
371 : * )
372 : * [1] => Array
373 : * (
374 : * [ID] => 34
375 : * [Name] => Tim
376 : * )
377 : * ...
378 : * )</pre>
379 : * setArrayIndexes($array_a, "ID") gibt folgendes Array zurück:
380 : * <pre>Array
381 : * (
382 : * [8] => Array
383 : * (
384 : * [ID] => 8
385 : * [Name] => Max
386 : * )
387 : * [34] => Array
388 : * (
389 : * [ID] => 34
390 : * [Name] => Tim
391 : * )
392 : * ...
393 : * )</pre>
394 : * Die Reihenfolge der Array-Elemente wird dabei nicht verändert,
395 : * ein Durchlauf mit foreach ist also weiterhin möglich.
396 : *
397 : * @access public
398 : * @author Clemens Weiß <clemens.weiss@mni.fh-giessen.de>
399 : * @param array $array - Ausgangs-Array
400 : * @param string $index - Index
401 : * @return array - Überarbeitetes Array oder im Fehlerfall unverändertes Ausgangs-Array
402 : */
403 : function setArrayIndexes($array, $index) {
404 0 : if (!is_array($array)) return array();
405 0 : $new_array = array();
406 0 : foreach($array as $element) {
407 0 : if (!in_array($index, array_keys($element))) return $array;
408 0 : else $new_array[$element[$index]] = $element;
409 0 : }
410 0 : return $new_array;
411 : }
412 :
413 : // B.S.
414 : /**
415 : * Generiert ein Cache Objekt für installierte Module zur Verminderung von DB Abfragen
416 : *
417 : * @access public
418 : * @return array - Cache Objekt
419 : */
420 : function getInstallCacheObject() {
421 0 : global $db;
422 0 : $moduleGroups = $db->get_results("SELECT id_name, ID FROM modulegroups");
423 0 : $courses = $db->get_results("SELECT ID, Modules FROM courses");
424 0 : $moduleCache = array();
425 0 : $courseCache = array();
426 0 : if (sizeof($moduleGroups) > 0) {
427 0 : foreach($moduleGroups as $moduleGroup) {
428 0 : $mName = $moduleGroup->id_name;
429 0 : $moduleCache["$mName"] = $moduleGroup->ID;
430 0 : }
431 0 : }
432 0 : if (sizeof($courses) > 0) {
433 0 : foreach($courses as $course) {
434 0 : $cID = $course->ID;
435 0 : $courseCache["$cID"] = $course->Modules;
436 0 : }
437 0 : }
438 : // Zwei Cache Arrays: courses->ID => courses->Modules, modulegroups->id_name => modulegroups->ID
439 : $cacheObject = array(
440 0 : 'courses' => $courseCache,
441 : 'moduleGroups' => $moduleCache
442 0 : );
443 0 : return $cacheObject;
444 : }
445 :
446 : /**
447 : * Gibt zurück, ob eine Modulgruppe im angegebenen Kurs aktiviert ist.
448 : *
449 : * @static
450 : * @access public
451 : * @author Clemens Weiß <clemens.weiss@mni.fh-giessen.de>
452 : * @param string $name Eindeutiger Bezeichner der Modulgruppe (Feld id_name)
453 : * @param int $courseID Kurs-ID, aktueller Kurs, wenn nicht angegeben
454 : * @param $cacheObject enthält Daten-Cache, vermeidet Datenbankabfragen
455 : * @return bool true, wenn Modulgruppe aktiviert, sonst false
456 : */
457 : function isInstalled($name, $courseID = -1, $cacheObject = null) {
458 0 : global $db, $settings;
459 0 : $dbp = $settings["dbPrefix"];
460 0 : if ($courseID === -1) {
461 0 : $courseID = $_SESSION["course"];
462 0 : }
463 0 : if (!preg_match("/^[a-z_]+$/", $name) || strval(intval($courseID)) != $courseID || $courseID < 0) {
464 0 : return false;
465 : }
466 0 : if ($cacheObject != null) {
467 0 : $moduleGroups = $cacheObject["moduleGroups"]; // {name, id}
468 0 : $courses = $cacheObject["courses"];
469 0 : if (sizeof($moduleGroups) > 0 && sizeof($courses) > 0) {
470 0 : if ($courseID == 0 && !empty($moduleGroups["$name"]))
471 0 : return true;
472 0 : $modules = $courses["$courseID"];
473 0 : $id = $moduleGroups["$name"];
474 0 : return (int)$modules&(int)pow(2, (int)$id-2);
475 : }
476 0 : }
477 : else {
478 0 : $id = $db->get_var("SELECT ID FROM {$dbp}modulegroups WHERE id_name='$name'");
479 0 : if (!empty($id)) {
480 0 : if ($courseID == 0)
481 0 : return true;
482 0 : $modules = $db->get_var("SELECT Modules FROM {$dbp}courses WHERE ID='$courseID'");
483 0 : return (int)$modules&(int)pow(2, (int)$id-2);
484 : }
485 : }
486 0 : return false;
487 : }
488 : /**
489 : * Kürzt den Text auf eine angegebene Anzahl Zeichen bis zum letzten Leerzeichen.
490 : * Entfernt Formatierungstags und ersetzt Zeilenumbrüche optional durch Leerzeichen.
491 : *
492 : * @static
493 : * @access public
494 : * @author Clemens Weiß <clemens.weiss@mni.fh-giessen.de>
495 : * @param string $text Zu kürzender Text
496 : * @param int $length Maximale Anzahl Zeichen
497 : * @param string $append Auslassungszeichen, die dem gekürzten Text angehängt werden
498 : * @param bool $removeNewlines Gibt an, ob Zeilenumbrüche und mehrfache Leerzeichen durch einfach ersetzt werden sollen
499 : * @return string Gekürzter Text
500 : */
501 : function chopText($text, $length = 250, $append = "...", $removeNewlines = true) {
502 0 : $bbcode = new BBCode();
503 0 : $text = $bbcode->stripTags($text);
504 0 : if ($removeNewlines) {
505 0 : $text = preg_replace("/(\015\012|\015|\012|\s)+/", " ", $text);
506 0 : }
507 0 : if (strlen($text) > $length) {
508 0 : $text = substr($text, 0, $length);
509 0 : $text = substr($text, 0, strrpos($text, " "));
510 0 : $text.= $append;
511 0 : }
512 0 : return $text;
513 : }
514 : /**
515 : * Hebt Wörter in einem Text farblich und fett hervor.
516 : *
517 : * @static
518 : * @access public
519 : * @author Clemens Weiß <clemens.weiss@mni.fh-giessen.de>
520 : * @param string $text Zu durchsuchender Text
521 : * @param array $words Array mit den hervorzuhebenden Wörtern
522 : * @param array $colors Array mit den zu verwendenden Hintergrundfarben
523 : * @return string Text mit mittels span-Tag hervorgehobenen Wörtern
524 : */
525 : function highlightWords($text, $words, $colors = array("#ffff66", "#a0ffff", "#99ff99", "#ff9999", "#ff66ff")) {
526 0 : if (!is_array($words) || !is_array($colors) || empty($colors)) {
527 0 : return $text;
528 : }
529 0 : $c = count($colors);
530 0 : $i = 0;
531 0 : foreach($words as $word) {
532 0 : if (strlen($word) >= 3) {
533 0 : $text = preg_replace('/('.preg_quote($word, '/') .')(?=[^>]*\<)/i', '<span style="color: black; background-color:'.$colors[$i++%$c].'; font-weight: bold;">$1</span>', $text);
534 0 : }
535 0 : }
536 0 : return $text;
537 : }
538 : }
|